package com.bizmda.bizsip.sink.controller;

import cn.hutool.json.JSONObject;
import com.bizmda.bizsip.common.BizException;
import com.bizmda.bizsip.common.BizMessage;
import com.bizmda.bizsip.common.BizResultEnum;
import com.bizmda.bizsip.common.BizUtils;
import com.bizmda.bizsip.converter.Converter;
import com.bizmda.bizsip.sink.connector.BeanSinkConnector;
import com.bizmda.bizsip.sink.connector.Connector;
import com.bizmda.bizsip.sink.connector.SinkBeanSinkConnector;
import com.bizmda.bizsip.sink.connector.sinkbean.JSONObjectSinkBeanInterface;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RestController;

import javax.annotation.PostConstruct;
import javax.servlet.http.HttpServletResponse;

/**
 * @author 史正烨
 */
@Slf4j
@RestController
public class SinkController {
    @Value("${bizsip.sink-id}")
    private String sinkId;

    private Converter converter = null;
    private Connector connector = null;

    @PostConstruct
    public void init() {
        if (this.sinkId == null) {
            log.error("配置文件中sink-id没有配置，SinkController初始化失败！");
            return;
        }
        this.converter = Converter.getSinkConverter(this.sinkId);
        this.connector = Connector.getSinkConnector(this.sinkId);
    }

    @PostMapping(value = "/sink", consumes = "application/json", produces = "application/json")
    public BizMessage<JSONObject> doService(@RequestBody BizMessage<JSONObject> inMessage, HttpServletResponse response) {
        JSONObject outMessage = null;
        if (this.sinkId == null) {
            return BizMessage.buildFailMessage(inMessage,new BizException(BizResultEnum.SINK_SINKID_IS_NULL));
        }
        try {
            outMessage = this.process(inMessage.getData());
            return BizMessage.buildSuccessMessage(inMessage,outMessage);
        } catch (BizException e) {
            return BizMessage.buildFailMessage(inMessage,e);
        }
    }

    private JSONObject process(JSONObject inMessage) throws BizException {
        log.trace("Sink传入消息:\n{}", BizUtils.buildJsonLog(inMessage));

        boolean isConverter = true;
        if ((this.connector.getSinkConnector() instanceof BeanSinkConnector)) {
            isConverter = false;
        } else if (this.connector.getSinkConnector() instanceof SinkBeanSinkConnector) {
            if (((SinkBeanSinkConnector) this.connector.getSinkConnector()).getSinkBean() instanceof JSONObjectSinkBeanInterface) {
                isConverter = false;
            }
        }

        if (!isConverter) {
            log.debug("Sink通过Connect[{}]调用服务", this.connector.getSinkConnector().getType());
            JSONObject jsonObject = this.connector.process(inMessage);
            log.trace("Sink服务返回消息:\n{}", BizUtils.buildJsonLog(jsonObject));
            return jsonObject;
        }
        log.debug("Sink调用Convert[{}]打包", this.converter.getConverter().getType());
        byte[] packedMessage = this.converter.pack(inMessage);
        log.trace("Sink打包后消息:\n{}", BizUtils.buildHexLog(packedMessage));
        log.debug("Sink通过Connect[{}]调用服务", this.connector.getSinkConnector().getType());
        byte[] returnMessage = this.connector.process(packedMessage);
        log.trace("Sink服务返回消息:\n{}", BizUtils.buildHexLog(returnMessage));
        log.debug("Sink调用Convert[{}]解包", this.converter.getConverter().getType());
        JSONObject unpackedJsonObject = this.converter.unpack(returnMessage);
        log.trace("Sink返回消息:\n{}", BizUtils.buildJsonLog(unpackedJsonObject));
        return unpackedJsonObject;
    }
}